package www.wen.com.common.lib.data.repository

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import okhttp3.MultipartBody
import retrofit2.Call
import www.wen.com.common.lib.data.db.AppDbHelper
import www.wen.com.common.lib.data.entities.*
import www.wen.com.common.lib.data.network.ApiHelper
import javax.inject.Inject
import javax.inject.Singleton

/**e
 * @author WEN
 * @Description: 管理所有接口的代理
 * @date 2020/11/2 16:15
 */
@Singleton
class AppDataManagerImpl @Inject constructor(
        private val apiHelper: ApiHelper,
        private val appDbHelper: AppDbHelper,
) : AppDataManager {

    override suspend fun <T> insertCache(key: String, cacheEntity: T): Boolean {
        return appDbHelper.insertCache(key, cacheEntity)
    }

    override suspend fun <T> findByKey(key: String): T? = appDbHelper.findByKey(key)

    override suspend fun <T> queryCache(key: String, error: Result.Error, successBlock: suspend (CoroutineScope, T) -> Unit, errorBlock: suspend (CoroutineScope, Result.Error) -> Unit) =
            appDbHelper.queryCache(key, error, successBlock, errorBlock)

    override suspend fun requestVerifyCode(requestVerifyBody: RequestVerifyBody): Result<VerifyCodeEntity> =
            apiHelper.requestVerifyCode(requestVerifyBody)

    override suspend fun requestChannelId(channelId: Long): Result<ChannelInfo> =
            apiHelper.requestChannelId(channelId)

    override suspend fun patchChannel(
            channelId: Long,
            requestBodyParameter: RequestBodyParameter,
    ): Result<ChannelInfo> = apiHelper.patchChannel(channelId, requestBodyParameter)

    override suspend fun deleteChannel(channelId: Long): Result<String> = apiHelper.deleteChannel(channelId)

    override suspend fun deleteGroup(groupId: String): Result<String> = apiHelper.deleteGroup(groupId)

    override suspend fun requestInviteList(serverId: String, page: Int, size: Int): Result<InvitationEntity> =
            apiHelper.requestInviteList(serverId, page, size)

    override suspend fun requestRegister(
            type: String,
            requestRegisterBody: RequestRegisterBody,
    ): Result<LoginInfo> = apiHelper.requestRegister(type, requestRegisterBody)

    override suspend fun requestSmsLogin(requestRegisterBody: RequestRegisterBody): Result<LoginInfo> =
            apiHelper.requestSmsLogin(requestRegisterBody)

    override suspend fun requestAccessToken(code: String): Result<WxEntity> =
            apiHelper.requestAccessToken(code)

    override suspend fun requestResetPassword(body: RequestBodyParameter): Result<UseInfoEntity> =
            apiHelper.requestResetPassword(body)

    override suspend fun requestUploadOssFile(
            partMap: Map<String, okhttp3.RequestBody>,
            vararg file: MultipartBody.Part,
    ): Result<UpOssFileEntity> =
            apiHelper.requestUploadOssFile(partMap, *file)

    override suspend fun searchUserByNickName(nickName: String): Result<UseInfoEntity> = apiHelper.searchUserByNickName(nickName)

    override suspend fun requestUserInfoById(id: String): Result<UseInfoEntity> =
        apiHelper.requestUserInfoById(id)

    override suspend fun requestLoginOrRegisterByToken(
            type: String,
            body: RequestLoginOrRegisterByToken,
    ): Result<EmptyEntity> = apiHelper.requestLoginOrRegisterByToken(type, body)

    override suspend fun requestRegisterByToken(body: RequestLoginOrRegisterByToken): Result<LoginInfo> = apiHelper.requestRegisterByToken(body)

    override suspend fun requestCreateServer(body: RequestBodyParameter): Result<ServerEntity> =
            apiHelper.requestCreateServer(body)

    override suspend fun requestServerSelfList(
            page: Int,
            size: Int,
    ): Result<ServerSelfListEntity> =
            apiHelper.requestServerSelfList(page, size)

    override suspend fun requestServerGroupList(serverId: String): Result<ServerGroupEntity> =
            apiHelper.requestServerGroupList(serverId)

    override fun createServerFlow(
            body: RequestBodyParameter,
    ): Flow<Result.Success<ServerEntity>> {
        return flow {
            val result = requestCreateServer(body)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun registerByTokenFlow(
            body: RequestLoginOrRegisterByToken,
    ): Flow<Result.Success<LoginInfo>> {
        return flow {
            val result = requestRegisterByToken(body)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override suspend fun requestServersMemberList(
            serverId: String,
            nickName: String?,
            page: Int,
            size: Int,
    ): Result<ServiceMemberListEntity> = apiHelper.requestServersMemberList(serverId, nickName, page, size)

    override suspend fun requestUsersOnlineStatus(accids: Array<String>): Result<List<UseInfoEntity>> =
            apiHelper.requestUsersOnlineStatus(accids)

    override suspend fun requestServerList(
            serverIdOrName: String?,
            recommendFlag: String?,
            page: Int?,
            size: Int?,
    ): Result<ServerListEntity> = apiHelper.requestServerList(serverIdOrName, recommendFlag, page, size)

    override suspend fun requestInviteOrAdd(type: String, body: RequestBodyParameter): Result<String> =
            apiHelper.requestInviteOrAdd(type, body)

    override suspend fun requestVerifyMobile(body: RequestBodyParameter): Result<String> =
            apiHelper.requestVerifyMobile(body)


    override suspend fun requestServerDetails(serverId: String): Result<ServerInfo> =
            apiHelper.requestServerDetails(serverId)

    override suspend fun requestServerPreview(serverId: String): Result<ServerSelfListEntity.Content> =
            apiHelper.requestServerPreview(serverId)

    override suspend fun requestUpdateServerInfo(serverId: String, body: RequestBodyParameter): Result<ServerUpdateInfoEntity> =
            apiHelper.requestUpdateServerInfo(serverId, body)

    override suspend fun requestCreateChannel(body: RequestBodyParameter): Result<ChannelEntity> =
            apiHelper.requestCreateChannel(body)

    override suspend fun requestServerGroup(serverId: String): Result<List<GroupingEntity>> =
            apiHelper.requestServerGroup(serverId)

    override suspend fun requestServerShareUrl(body: RequestBodyParameter): Result<ShareUrlEntity> =
            apiHelper.requestServerShareUrl(body)

    override suspend fun requestMemberSetting(id: String, body: RequestBodyParameter): Result<String> =
            apiHelper.requestMemberSetting(id, body)

    override suspend fun requestCreateNewGroup(body: RequestBodyParameter): Result<GroupingEntity> =
            apiHelper.requestCreateNewGroup(body)

    override suspend fun requestDeleteServer(serverId: String): Result<String> =
            apiHelper.requestDeleteServer(serverId)

    override suspend fun requestChangeOwnerOrKick(type: String, body: RequestBodyParameter): Result<String> =
            apiHelper.requestChangeOwnerOrKick(type, body)

    override suspend fun requestChangeMobile(body: RequestBodyParameter): Result<String> =
            apiHelper.requestChangeMobile(body)

    override suspend fun requestUserInfo(body: RequestBodyParameter): Result<UseInfoEntity> =
            apiHelper.requestUserInfo(body)

    override suspend fun requestUserInfo(): Result<UseInfoEntity> =
            apiHelper.requestUserInfo()

    override suspend fun requestShareFind(body: RequestBodyParameter): Result<JoinServerEntity> =
            apiHelper.requestShareFind(body)

    override suspend fun requestMemberInvite(body: RequestBodyParameter): Result<String> =
            apiHelper.requestMemberInvite(body)

    override suspend fun requestExitServers(serverId: String): Result<String> =
            apiHelper.requestExitServers(serverId)

    override suspend fun requestBatch(body: List<RequestBodyParameter>): Result<List<ChannelBatchEntity>> =
            apiHelper.requestBatch(body)

    override suspend fun requestGroupSort(body: List<RequestBodyParameter>): Result<List<ChannelBatchEntity>> =
            apiHelper.requestGroupSort(body)

    override suspend fun requestStartPage(size: Int, page: Int): Result<StartPageEntity> =
            apiHelper.requestStartPage(size, page)

    override suspend fun requestProtocol(map: Map<String, String>): Result<ProtocolEntity> =
            apiHelper.requestProtocol(map)

    override suspend fun requestServerOfficial(): Result<ServerSelfListEntity.Content> =
            apiHelper.requestServerOfficial()

    override suspend fun requestUpdateGroup(groupId: String, body: RequestBodyParameter): Result<ServerGroupEntity.Content> =
            apiHelper.requestUpdateGroup(groupId,body)

    override suspend fun requestRemove(): Result<String> = apiHelper.requestRemove()

    override suspend fun requestTokenRevoke(): Result<String> = apiHelper.requestTokenRevoke()

    override fun addServerChannelTopMsg(body: RequestServerChannelTopMsgBodyParameter): Call<String> =
            apiHelper.addServerChannelTopMsg(body)

    override suspend fun getServerChannelTopMsgList(teamId: String): Result<TopMsgEntity> =
            apiHelper.getServerChannelTopMsgList(teamId)

    override fun deleteServerChannelTopMsg(uuid: String): Call<String> =
            apiHelper.deleteServerChannelTopMsg(uuid)

    override fun loginOrRegisterFlow(type: String, requestRegisterBody: RequestRegisterBody): Flow<Result.Success<LoginInfo>> {
        return flow {
            val result = requestRegister(type, requestRegisterBody)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun resetPasswordFlow(body: RequestBodyParameter): Flow<Result.Success<UseInfoEntity>> {
        return flow {
            val result = requestResetPassword(body)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun requestUserInfoByIdFlow(id: String): Flow<Result.Success<UseInfoEntity>> {
        return flow {
            val result = requestUserInfoById(id)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }


    override fun searchUserByNickNameFlow(nickName: String): Flow<Result.Success<UseInfoEntity>> {
        return flow {
            val result = searchUserByNickName(nickName)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun getServerMemberListFlow(serverId: String, nickName: String?, page: Int, size: Int): Flow<Result.Success<ServiceMemberListEntity>> {
        return flow {
            val result = requestServersMemberList(serverId, nickName, page, size)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun requestUsersOnlineStatusFlow(accids: Array<String>): Flow<Result.Success<List<UseInfoEntity>>> {
        return flow {
            val result = requestUsersOnlineStatus(accids)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun requestServerListFlow(
            serverIdOrName: String?,
            recommendFlag: String?,
            page: Int?,
            size: Int?,
    ): Flow<Result.Success<ServerListEntity>> {
        return flow {
            val result = requestServerList(serverIdOrName, recommendFlag, page, size)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun getServerChannelTopMsgListFlow(teamId: String): Flow<Result.Success<TopMsgEntity>> {
        return flow {
            val result = getServerChannelTopMsgList(teamId)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun requestChannelIdFlow(channelId: Long): Flow<Result.Success<ChannelInfo>> {
        return flow {
            val result = requestChannelId(channelId)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun serverGroupListFlow(serverId: String): Flow<Result.Success<ServerGroupEntity>> {
        return flow {
            val result = requestServerGroupList(serverId)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun groupSortFlow(body: List<RequestBodyParameter>): Flow<Result.Success<List<ChannelBatchEntity>>> {
        return flow {
            val result = requestGroupSort(body)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun deleteChannelFlow(channelId: Long): Flow<Result.Success<String>> {
        return flow {
            val result = deleteChannel(channelId)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun patchChannelFlow(channelId: Long, body: RequestBodyParameter): Flow<Result.Success<ChannelInfo>> {
        return flow {
            val result = patchChannel(channelId, body)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun userInfoFlow(body: RequestBodyParameter): Flow<Result.Success<UseInfoEntity>> {
        return flow {
            val result = requestUserInfo(body)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun smsLoginFlow(requestRegisterBody: RequestRegisterBody): Flow<Result.Success<LoginInfo>> {
        return flow {
            val result = requestSmsLogin(requestRegisterBody)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun accessTokenFlow(code: String): Flow<Result.Success<WxEntity>> {
        return flow {
            val result = requestAccessToken(code)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun <T> loginOrRegisterByTokenFlow(
            type: String,
            body: RequestLoginOrRegisterByToken,
            emitObject: (loginInfo: EmptyEntity) -> T,
    ): Flow<T> {
        return flow {
            val result = requestLoginOrRegisterByToken(type, body)
            if (result is Result.Success) {
                emit(emitObject.invoke(result.data))
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun uploadOssFileFlow(
            partMap: Map<String, okhttp3.RequestBody>,
            vararg file: MultipartBody.Part,
    ): Flow<Result.Success<UpOssFileEntity>> {
        return flow {
            val result = requestUploadOssFile(partMap, *file)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

    override fun updateServerInfoFlow(serverId: String, body: RequestBodyParameter): Flow<Result.Success<ServerUpdateInfoEntity>> {
        return flow {
            val result = requestUpdateServerInfo(serverId, body)
            if (result is Result.Success) {
                emit(result)
            } else {
                throw (result as Result.Error).exception
            }
        }
    }

}